package org.fitweb.fixture;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.apache.commons.lang.StringUtils.join;

public class XmlFormatter {
    private String xml;

    public static String format(String xml) {
        return new XmlFormatter(xml)
                .withTagsUpperCase()
                .withUnnecessarySpacesRemoved()
                .toString();
    }

    public XmlFormatter(String xml) {
        this.xml = xml;
    }

    public XmlFormatter withUnnecessarySpacesRemoved() {
        xml = xml.replaceAll(">\\s*<", "><");
        return this;
    }

    public XmlFormatter withLineBreaks() {
        xml = xml.replaceAll("><", ">\n<");
        return this;
    }

    public XmlFormatter withTagsUpperCase() {
        Matcher matcher = Pattern.compile("</?.*?>").matcher(xml);
        while (matcher.find()) {
            String matchingText = matcher.group(0);
            xml = xml.replaceAll(matchingText, matchingText.toUpperCase());
        }

        return this;
    }

    public XmlFormatter withIndentation(int spacesToIndent) {
        StringBuilder result = new StringBuilder();
        String[] lines = xml.split("\n");
        int depth = 0;
        String indent = joinUp(spacesToIndent, " ");
        for (String line : lines) {
            int direction = indentDirection(line);
            if (direction == -1) depth += direction;
            result.append(joinUp(depth, indent)).append(line).append("\n");
            if (direction == 1) depth += direction;
        }

        xml = result.toString();

        return this;
    }

    String substituteJavaProperties(String originalString) {
        Matcher matcher = Pattern.compile("\\$\\{(.*?)\\}").matcher(originalString);
        while (matcher.find()) {
            String matchingText = matcher.group(1);
            String propertyValue = Matcher.quoteReplacement(System.getProperty(matchingText));
            originalString = originalString.replaceAll("\\$\\{" + matchingText + "\\}", propertyValue);
        }

        return originalString;
    }

    private String joinUp(int spacesToIndent, String thingToJoin) {
        return join(new String[spacesToIndent + 1], thingToJoin);
    }

    private int indentDirection(String line) {
        int opens = line.split("<\\w").length - 1;
        int closes = line.split("</|/>").length - 1;
        return opens == closes ? 0 : opens > closes ? 1 : -1;
    }

    public String toString() {
        return xml;
    }
}
